package com.hq.ims.platform.controller;

import com.hq.ims.data.annotation.UserOperationMonitor;
import com.hq.ims.data.entity.PermissionAuthority;
import com.hq.ims.data.entity.PermissionGroup;
import com.hq.ims.data.entity.PermissionMenu;
import com.hq.ims.data.entity.PermissionRole;
import com.hq.ims.data.entityenum.EnumMenuOwnType;
import com.hq.ims.data.service.*;
import com.hq.ims.data.utils.ErrMsgConstant;
import com.hq.ims.data.utils.LocalConstant;
import com.hq.ims.data.vo.*;
import com.hq.mybatis.base.page.RequestPage;
import com.hq.utils.util.ObjectUtils;
import com.hq.utils.vo.ReturnVo;
import com.hq.web.annotations.GetJsonValue;
import com.hq.web.utils.SpringBootValidateUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

/**
 * 权限中心controller
 */
@Api(tags = "权限相关")
@RestController
@RequestMapping(LocalConstant.SYS_TYPE_PLATFORM_URL_PREFIX + "/permission")
public class PlatformPermissionController {

    @Resource
    private BasePermissionGroupService basePermissionGroupService;
    @Resource
    private BasePermissionAuthorityService basePermissionAuthorityService;
    @Resource
    private BasePermissionRoleService basePermissionRoleService;
    @Resource
    private BasePermissionMenuService basePermissionMenuService;
    @Resource
    private BasePermissionMapAuthorityUserService basePermissionMapAuthorityUserService;
    @Resource
    private BasePermissionMapAuthorityMenuService basePermissionMapAuthorityMenuService;
    @Resource
    private BasePermissionMapAuthorityRoleService basePermissionMapAuthorityRoleService;
    @Resource
    private BasePermissionMapRoleUserService basePermissionMapRoleUserService;

    //--------------------------- 菜单 -------------------------------------

    @ApiOperation(value = "获取菜单列表", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @PostMapping(value = "/menu/getTree", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<List<PermissionMenuMapstruct.PermissionMenuTreeVo>> menuGetTree(
            @GetJsonValue(zh = "菜单分类") EnumMenuOwnType ownType
    ) {
        List<PermissionMenuMapstruct.PermissionMenuTreeVo> tree = basePermissionMenuService.getTree(ownType);
        return ReturnVo.buildSuccess(tree);
    }

    @ApiOperation(value = "添加菜单", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @UserOperationMonitor
    @PostMapping(value = "/menu/add", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<Boolean> menuAdd(@RequestBody PermissionMenuMapstruct.SaveVo saveVo) {
        basePermissionMenuService.addMenu(saveVo);
        return ReturnVo.buildSuccess(true);
    }

    @ApiOperation(value = "更新菜单", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @UserOperationMonitor
    @PostMapping(value = "/menu/update", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<Boolean> updateMenu(@RequestBody PermissionMenuMapstruct.SaveVo saveVo) {
        basePermissionMenuService.updateMenu(saveVo);
        return ReturnVo.buildSuccess(true);
    }

    @ApiOperation(value = "菜单详情", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @PostMapping(value = "/menu/detail", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<PermissionMenuMapstruct.PermissionMenuVo> menuDetail(@GetJsonValue String menuId) {
        PermissionMenu permissionMenu = basePermissionMenuService.getById(menuId);
        PermissionMenuMapstruct.PermissionMenuVo vo = PermissionMenuMapstruct.INSTANCE.toPermissionMenuVo(permissionMenu);
        return ReturnVo.buildSuccess(vo);
    }

    @ApiOperation(value = "删除菜单", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @UserOperationMonitor
    @PostMapping(value = "/menu/delByMenuId", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<Boolean> menuDelByMenuId(@GetJsonValue(zh = "菜单ID") List<String> menuIdList) {
        basePermissionMenuService.delByMenuIdList(menuIdList);
        return ReturnVo.buildSuccess(true);
    }


    @ApiOperation(value = "移动菜单", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @UserOperationMonitor
    @PostMapping(value = "/menu/move", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<Boolean> moveMenu(
            @GetJsonValue(zh = "要移动的菜单") String curMenuId,
            @GetJsonValue(zh = "移动到目标的菜单") String targetMenuId
    ) {
        basePermissionMenuService.moveMenu(curMenuId, targetMenuId);
        return ReturnVo.buildSuccess(true);
    }

    @ApiOperation(value = "绑定菜单权限", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @UserOperationMonitor
    @PostMapping(value = "/menu/bindMenuAuth", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<Boolean> menuBindMenuAuth(
            @RequestBody PermissionMapAuthorityMenuMapstruct.BindMenuAuthorityVo saveVo
    ) {
        basePermissionMapAuthorityMenuService.bindMenuAuthority(saveVo);
        return ReturnVo.buildSuccess(true);
    }


    //---------------------------- 获取用户权限 ----------------------------

    @ApiOperation(value = "根据用户id获取该用户所有去重后的权限点(树结构)", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @PostMapping(value = "/menu/getTreeMenuByUserIdAndCompanyId", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<List<PermissionMenuMapstruct.PermissionMenuTreeVo>> getUserMenuByUserIdTree(
            @GetJsonValue(zh = "用户Id") String userId,
            @GetJsonValue(zh = "公司Id") String companyId
    ) {
        List<PermissionMenuMapstruct.PermissionMenuTreeVo> dataList = basePermissionMenuService.getTreeByUserIdAndCompanyId(userId, companyId, EnumMenuOwnType.User);
        return ReturnVo.buildSuccess(dataList);
    }

    @ApiOperation(value = "根据用户id获取该用户所有去重后的权限点(扁平)", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @PostMapping(value = "/menu/getFlatMenuByUserIdAndCompanyId", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<List<PermissionMenuMapstruct.PermissionMenuVo>> getUserMenuByUserIdFlat(
            @GetJsonValue(zh = "用户Id") String userId,
            @GetJsonValue(zh = "公司Id") String companyId
    ) {
        List<PermissionMenuMapstruct.PermissionMenuVo> permissionMenuVoList = basePermissionMenuService.getMenuByUserIdAndCompanyId(userId, companyId, null);
        return ReturnVo.buildSuccess(permissionMenuVoList);
    }

    @ApiOperation(value = "获取用户权限ID列表", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @PostMapping(value = "/menu/getAuthIdList", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<List<String>> getAuthIdList(
            @GetJsonValue(zh = "用户ID") String userId,
            @GetJsonValue(zh = "公司ID") String companyId
    ) {
        List<String> dataList = basePermissionMapAuthorityUserService.getAuthIdListByUserIdAndCompanyId(userId, companyId);
        return ReturnVo.buildSuccess(dataList);
    }

    @ApiOperation(value = "绑定用户权限", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @UserOperationMonitor
    @PostMapping(value = "/menu/bindUserAuth", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<Boolean> bindUserAuth(
            @RequestBody PermissionMapAuthorityUserMapstruct.BindUserAuthVo saveVo
    ) {
        basePermissionMapAuthorityUserService.bindUserAuth(saveVo);
        return ReturnVo.buildSuccess(true);
    }

    @ApiOperation(value = "绑定用户角色", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @UserOperationMonitor
    @PostMapping(value = "/menu/bindUserRole", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<Boolean> bindUserRole(
            @RequestBody PermissionMapRoleUserMapstruct.BindUserRoleVo saveVo
    ) {
        basePermissionMapRoleUserService.bindUserRole(saveVo);
        return ReturnVo.buildSuccess(true);
    }


    //--------------------------- 角色相关 -------------------------------------

    @ApiOperation(value = "获取角色列表", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    @ApiImplicitParams({
    })
    @PostMapping(value = "/role/list", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<List<PermissionRoleMapstruct.PermissionRoleVo>> roleList(
            @RequestBody PermissionRoleMapstruct.PageSearchVo pageSearchVo
    ) {
        RequestPage page = new RequestPage(1, Long.MAX_VALUE);
        List<PermissionRoleMapstruct.PermissionRoleVo> voList = basePermissionRoleService.getPage(page, pageSearchVo);
        return ReturnVo.buildSuccess(voList);
    }

    @ApiOperation(value = "绑定角色权限", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @UserOperationMonitor
    @PostMapping(value = "/role/bindRoleAuth", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<Boolean> roleBindRoleAuth(@RequestBody PermissionMapAuthorityRoleMapstruct.BindRoleAuthVo saveVo) {
        SpringBootValidateUtils.validate(saveVo, PermissionMapAuthorityRoleMapstruct.PlatformBind.class);

        PermissionRole permissionRole = basePermissionRoleService.getById(saveVo.getPermissionRoleId());
        ObjectUtils.isNullThrow(permissionRole, ErrMsgConstant.PERMISSION_ROLE_NOT_EXISTS);
        saveVo.setCompanyId(permissionRole.getCompanyId());

        basePermissionMapAuthorityRoleService.bindRoleAuth(saveVo);
        return ReturnVo.buildSuccess(true);
    }

    @ApiOperation(value = "获取角色和权限ID", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @UserOperationMonitor
    @PostMapping(value = "/role/getBindAuthIdDetail", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<PermissionRoleMapstruct.PermissionRoleVo> roleGetBindAuthDetail(
            @GetJsonValue(zh = "角色ID") String permissionRoleId
    ) {
        PermissionRoleMapstruct.PermissionRoleVo vo = basePermissionRoleService.getBindAuthDetail(permissionRoleId);
        return ReturnVo.buildSuccess(vo);
    }


    @ApiOperation(value = "创建角色", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @UserOperationMonitor
    @PostMapping(value = "/role/add", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<Boolean> addRole(@RequestBody PermissionRoleMapstruct.SaveVo saveVo) {
        basePermissionRoleService.addRole(saveVo);
        return ReturnVo.buildSuccess(true);
    }

    @ApiOperation(value = "获取角色", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @PostMapping(value = "/role/detail", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<PermissionRoleMapstruct.PermissionRoleVo> roleDetail(@GetJsonValue(zh = "角色ID") String permissionRoleId) {
        PermissionRole permissionRole = basePermissionRoleService.getById(permissionRoleId);
        PermissionRoleMapstruct.PermissionRoleVo vo = PermissionRoleMapstruct.INSTANCE.toPermissionRoleVo(permissionRole);
        return ReturnVo.buildSuccess(vo);
    }


    @ApiOperation(value = "更新角色", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @UserOperationMonitor
    @PostMapping(value = "/role/update", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<Boolean> roleUpdate(@RequestBody PermissionRoleMapstruct.SaveVo saveVo) {
        basePermissionRoleService.updateRole(saveVo);
        return ReturnVo.buildSuccess(true);
    }

    @ApiOperation(value = "删除角色", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @UserOperationMonitor
    @PostMapping(value = "/role/delByRoleId", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<Boolean> roleDelByRoleId(@GetJsonValue String permissionRoleId) {
        basePermissionRoleService.delByRoleId(permissionRoleId);
        return ReturnVo.buildSuccess(true);
    }

    //--------------------------- 权限组相关 -------------------------------------

    @ApiOperation(value = "获取权限组列表不分页", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @PostMapping(value = "/authority/list", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<List<PermissionAuthortyMapstruct.PermissionAuthorityVo>> authorityList(
            @RequestBody PermissionAuthortyMapstruct.PageSearchVo searchVo
    ) {
        RequestPage page = new RequestPage(1, Long.MAX_VALUE);
        List<PermissionAuthortyMapstruct.PermissionAuthorityVo> voList = basePermissionAuthorityService.getPage(page, searchVo);
        return ReturnVo.buildSuccess(voList);
    }

    @ApiOperation(value = "权限添加", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @UserOperationMonitor
    @PostMapping(value = "/authority/add", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<Boolean> authorityAdd(
            @RequestBody PermissionAuthortyMapstruct.SaveVo saveVo
    ) {
        basePermissionAuthorityService.addData(saveVo);
        return ReturnVo.buildSuccess(true);
    }

    @ApiOperation(value = "权限更新", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @UserOperationMonitor
    @PostMapping(value = "/authority/update", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<Boolean> authorityUpdate(
            @RequestBody PermissionAuthortyMapstruct.SaveVo saveVo
    ) {
        basePermissionAuthorityService.updateAuth(saveVo);
        return ReturnVo.buildSuccess(true);
    }

    @ApiOperation(value = "删除权限", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @UserOperationMonitor
    @PostMapping(value = "/authority/delByAuthId", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<Boolean> authorityDelByAuthId(@GetJsonValue(zh = "权限ID") String permissionAuthorityId) {
        basePermissionAuthorityService.delByAuthId(permissionAuthorityId);
        return ReturnVo.buildSuccess(true);
    }

    @ApiOperation(value = "权限详情", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @PostMapping(value = "/authority/detail", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<PermissionAuthortyMapstruct.PermissionAuthorityVo> authorityDetail(
            @GetJsonValue String permissionAuthorityId
    ) {
        PermissionAuthority permissionAuthority = basePermissionAuthorityService.getById(permissionAuthorityId);
        PermissionAuthortyMapstruct.PermissionAuthorityVo vo = PermissionAuthortyMapstruct.INSTANCE.toPermissionAuthorityVo(permissionAuthority);
        return ReturnVo.buildSuccess(vo);
    }

    @ApiOperation(value = "绑定权限角色", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @UserOperationMonitor
    @PostMapping(value = "/authority/bindAuthRole", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<Boolean> authorityBindAuthRole(
            @RequestBody PermissionMapAuthorityRoleMapstruct.BindAuthRoleVo saveVo
    ) {
        PermissionAuthority permissionAuthority = basePermissionAuthorityService.getById(saveVo.getPermissionAuthorityId());
        ObjectUtils.isNullThrow(permissionAuthority, ErrMsgConstant.PERMISSION_AUTH_NOT_EXISTS);
        saveVo.setCompanyId(permissionAuthority.getCompanyId());
        basePermissionMapAuthorityRoleService.bindAuthRole(saveVo);
        return ReturnVo.buildSuccess(true);
    }

    @ApiOperation(value = "获取权限绑定的角色", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @PostMapping(value = "/authority/getBindAuthRoleDetail", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<PermissionAuthortyMapstruct.PermissionAuthorityVo> authorityGetBindAuthRoleDetail(
            @GetJsonValue(zh = "权限ID") String permissionAuthorityId
    ) {
        PermissionAuthortyMapstruct.PermissionAuthorityVo vo = basePermissionAuthorityService.getBindAuthRoleDetail(permissionAuthorityId);
        return ReturnVo.buildSuccess(vo);
    }

    @ApiOperation(value = "绑定权限菜单", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @UserOperationMonitor
    @PostMapping(value = "/authority/bindAuthMenu", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<Boolean> authorityBindAuthMenu(
            @RequestBody PermissionMapAuthorityMenuMapstruct.BindAuthorityMenuVo saveVo
    ) {
        PermissionAuthority permissionAuthority = basePermissionAuthorityService.getById(saveVo.getPermissionAuthorityId());
        ObjectUtils.isNullThrow(permissionAuthority, ErrMsgConstant.PERMISSION_AUTH_NOT_EXISTS);
        saveVo.setCompanyId(permissionAuthority.getCompanyId());
        basePermissionMapAuthorityMenuService.bindAuthorityMenu(saveVo);
        return ReturnVo.buildSuccess(true);
    }

    @ApiOperation(value = "获取权限绑定的菜单", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @PostMapping(value = "/authority/getBindAuthMenuDetail", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<PermissionAuthortyMapstruct.PermissionAuthorityVo> authorityGetBindAuthMenuDetail(
            @GetJsonValue(zh = "权限ID") String permissionAuthorityId
    ) {
        PermissionAuthortyMapstruct.PermissionAuthorityVo vo = basePermissionAuthorityService.getBindAuthMenuDetail(permissionAuthorityId);
        return ReturnVo.buildSuccess(vo);
    }


    //---------------------------- 分类组 ----------------------------

    @ApiOperation(value = "获取组名称列表", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @PostMapping(value = "/group/list", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<List<PermissionGroupMapstruct.PermissionGroupVo>> groupList(
            @RequestBody PermissionGroupMapstruct.PageSearchVo searchVo
    ) {
        RequestPage page = new RequestPage(1, Long.MAX_VALUE);
        List<PermissionGroupMapstruct.PermissionGroupVo> voList = basePermissionGroupService.getPage(page, searchVo);
        return ReturnVo.buildSuccess(voList);
    }

    @ApiOperation(value = "组添加", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @UserOperationMonitor
    @PostMapping(value = "/group/add", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<Boolean> groupAdd(
            @RequestBody PermissionGroupMapstruct.SaveVo saveVo
    ) {
        basePermissionGroupService.addData(saveVo);
        return ReturnVo.buildSuccess(true);
    }

    @ApiOperation(value = "组更新", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @UserOperationMonitor
    @PostMapping(value = "/group/edit", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<Boolean> groupEdit(
            @RequestBody PermissionGroupMapstruct.SaveVo saveVo
    ) {
        basePermissionGroupService.editData(saveVo);
        return ReturnVo.buildSuccess(true);
    }

    @ApiOperation(value = "组详情", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @UserOperationMonitor
    @PostMapping(value = "/group/detail", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<PermissionGroupMapstruct.PermissionGroupVo> groupDetail(
            @GetJsonValue("组ID") String permissionGroupId
    ) {
        PermissionGroup permissionGroup = basePermissionGroupService.getById(permissionGroupId);
        PermissionGroupMapstruct.PermissionGroupVo vo = PermissionGroupMapstruct.INSTANCE.toPermissionGroupVo(permissionGroup);
        return ReturnVo.buildSuccess(vo);
    }

    @ApiOperation(value = "删除分类组", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({
    })
    @UserOperationMonitor
    @PostMapping(value = "/group/del", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ReturnVo<Boolean> groupDel(
            @GetJsonValue(zh = "组ID") String permissionGroupId
    ) {
        basePermissionGroupService.delData(permissionGroupId);
        return ReturnVo.buildSuccess(true);
    }

}
